using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Core.Service;
using Furion;
using Furion.FriendlyException;

namespace Admin.NET.Application.Util;

/// <summary>
/// 协议插件--工具类
/// </summary>
public static class AggrementPluginUtil
{
	public static ConcurrentDictionary<string, IAggrementPlugin> _pluginDic = new ConcurrentDictionary<string, IAggrementPlugin>();

	public static IAggrementPlugin? GetPluginService(string assemblyName, string filePath, string className = "Aggrement", bool fg = false)
	{
		IAggrementPlugin docking = null;
		if (!fg && _pluginDic.ContainsKey(assemblyName))
		{
			return _pluginDic[assemblyName];
		}
		filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, filePath);
		if (File.Exists(filePath))
		{
			if (!_pluginDic.ContainsKey(assemblyName))
			{
				byte[] assemblyBuf = File.ReadAllBytes(filePath);
				Assembly assembly = Assembly.Load(assemblyBuf);
				docking = assembly.CreateInstance(assemblyName + "." + className) as IAggrementPlugin;
				if (docking != null)
				{
					_pluginDic.TryAdd(assemblyName, docking);
				}
				return docking;
			}
			if (fg)
			{
				_pluginDic[assemblyName] = docking;
			}
			return _pluginDic[assemblyName];
		}
		throw new Exception("当前程序集不存在");
	}

	public static void Init(Dictionary<string, string> plugins, out string msg)
	{
		msg = "";
		foreach (KeyValuePair<string, string> plugin in plugins)
		{
			if (_pluginDic.ContainsKey(plugin.Key))
			{
				_pluginDic.Remove(plugin.Key, out var _p);
				if (_p != null)
				{
					_p.Stop();
					_p = null;
				}
			}
			IAggrementPlugin _plugin = GetPluginService(plugin.Key, plugin.Value);
			if (_plugin == null)
			{
				msg = msg + "当前插件初始化失败" + plugin.Key + "请检查插件是否合理/r/n";
			}
		}
	}

	/// <summary>
	/// 根据电表信息获取插件
	/// </summary>
	/// <param name="device"></param>
	/// <param name="isDTU">判断是否是dtu</param>
	/// <returns></returns>
	public static (IAggrementPlugin, BrandModel) GetPlugin(ElectricMeter device, bool isDTU = false)
	{
		SysCacheService _cache = App.GetService<SysCacheService>();
		List<BrandModel> brandModels = _cache.Get<List<BrandModel>>("BrandModels");
		List<AggrementPluginManage> plugins = _cache.Get<List<AggrementPluginManage>>("AggrementPlugins");
		if (brandModels.Count == 0 || plugins.Count == 0)
		{
			throw Oops.Bah("插件服务缓存失败，请稍后重试");
		}
		BrandModel currentModel = null;
		AggrementPluginManage currentPlugin = null;
		if (device != null)
		{
			currentModel = brandModels.Where((BrandModel w) => w.Id == device.BrandId).FirstOrDefault();
			if (currentModel == null)
			{
				throw Oops.Bah("当前插件服务缓存失败，请稍后重试");
			}
		}
		bool flag = true;
		currentPlugin = plugins.Where((AggrementPluginManage w) => w.Id == currentModel.AggrementPluginId).FirstOrDefault();
		if (currentPlugin == null)
		{
			throw Oops.Bah("当前插件服务缓存失败，请稍后重试");
		}
		IAggrementPlugin pluginService = GetPluginService(currentPlugin.AssemblyName, currentPlugin.Path);
		if (pluginService == null)
		{
			throw Oops.Bah("当前插件获取失败");
		}
		if (!pluginService.IsRunning())
		{
			throw Oops.Bah("当前插件未运行");
		}
		return (pluginService, currentModel);
	}

	/// <summary>
	/// 根据电表信息获取插件
	/// </summary>
	/// <param name="device"></param>
	/// <param name="isDTU">判断是否是dtu</param>
	/// <returns></returns>
	public static (IAggrementPlugin, BrandModel) GetPlugin(WaterDevice device, bool isDTU = false)
	{
		SysCacheService _cache = App.GetService<SysCacheService>();
		List<BrandModel> brandModels = _cache.Get<List<BrandModel>>("BrandModels");
		List<AggrementPluginManage> plugins = _cache.Get<List<AggrementPluginManage>>("AggrementPlugins");
		if (brandModels.Count == 0 || plugins.Count == 0)
		{
			throw Oops.Bah("插件服务缓存失败，请稍后重试");
		}
		BrandModel currentModel = null;
		AggrementPluginManage currentPlugin = null;
		if (device != null)
		{
			currentModel = brandModels.Where((BrandModel w) => w.Id == device.BrandId).FirstOrDefault();
			if (currentModel == null)
			{
				throw Oops.Bah("当前插件服务缓存失败，请稍后重试");
			}
		}
		bool flag = true;
		currentPlugin = plugins.Where((AggrementPluginManage w) => w.Id == currentModel.AggrementPluginId).FirstOrDefault();
		if (currentPlugin == null)
		{
			throw Oops.Bah("当前插件服务缓存失败，请稍后重试");
		}
		IAggrementPlugin pluginService = GetPluginService(currentPlugin.AssemblyName, currentPlugin.Path);
		if (pluginService == null)
		{
			throw Oops.Bah("当前插件获取失败");
		}
		if (!pluginService.IsRunning())
		{
			throw Oops.Bah("当前插件未运行");
		}
		return (pluginService, currentModel);
	}
}
